package com.lwc.backendsinglestructure.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.generator.CodeGenerator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.lwc.backendsinglestructure.annotation.DistributeLock;
import com.lwc.backendsinglestructure.utils.UnsignedMathGenerator;
import com.lwc.backendsinglestructure.domain.dto.user.CaptchasForm;
import com.lwc.backendsinglestructure.domain.dto.user.ForgetForm;
import com.lwc.backendsinglestructure.domain.dto.user.LoginForm;
import com.lwc.backendsinglestructure.domain.dto.user.RegisterForm;
import com.lwc.backendsinglestructure.domain.entity.User;
import com.lwc.backendsinglestructure.domain.vo.CaptchaVo;
import com.lwc.backendsinglestructure.exception.BusinessException;
import com.lwc.backendsinglestructure.exception.ErrorCode;
import com.lwc.backendsinglestructure.mapper.UserMapper;
import com.lwc.backendsinglestructure.service.UserService;
import com.lwc.backendsinglestructure.strategy.LoginHandler;
import com.lwc.backendsinglestructure.strategy.RegisterStrategy;
import com.lwc.backendsinglestructure.strategy.SendHandler;
import com.lwc.backendsinglestructure.strategy.registerStrategy.RegisterStrategyFactory;
import com.lwc.backendsinglestructure.utils.cache.CacheUtil;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 用户 服务层实现。
 *
 * @author <a href="https://gitee.com/liu-wenchan">程序员Rel</a>
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>  implements UserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private CacheUtil cacheUtil;
    @Autowired
    List<LoginHandler> loginHandlers;

    @Override
    public long userRegister(String userAccount, String userPassword, String checkPassword) {
        return 0;
    }

    /**
     * 登录
     * @param loginRequest
     */
    @Override
    public User login(LoginForm loginRequest) {
        // 1.获取登录类型
        String type = loginRequest.getType();
        // 2.根据不同的登录策略选择不同的登录方法
        LoginHandler loginHandler = (LoginHandler)SpringUtil.getBean(loginRequest.getType() + "_Login");
        User user = loginHandler.login(loginRequest);
        // 3.将user进行脱敏处理 ==》 userVo 返回给前端保存起来
        // 会话登录：参数填写要登录的账号id，建议的数据类型：long | int | String， 不可以传入复杂类型，如：User、Admin 等等
        StpUtil.login(user.getId());
        return user;
    }

    @Autowired
    private RegisterStrategyFactory registerStrategyFactory;

    /**
     * 注册
     * @param registerForm
     * @return
     */
    @Override
    public Boolean register(RegisterForm registerForm) {
        // 1.判断的注册类型是手机还是邮箱 (使用邮箱还是手机接受验证码进行登录)
        String type = registerForm.getType();
        RegisterStrategy registerStrategy = registerStrategyFactory.getRegisterStrategy(type);
        // 5。todo 暂时不校验再判断邮箱还是手机是否有重复注册（）
        return registerStrategy.register(registerForm);
    }


    /**
     * 发送验证码
     * @param captchasForm
     */
    @DistributeLock(business = "code", keyExpression = "#captchasForm.email")
    @Override
    public void sendCaptchas(CaptchasForm captchasForm) {
        SendHandler sendStrategy = (SendHandler) SpringUtil.getBean(captchasForm.getType() + "_SEND");
        Boolean sucess = sendStrategy.sendCaptcha(captchasForm);
        if (!sucess){
            throw new BusinessException(ErrorCode.SEND_CAPTCHA_ERROR);
        }
    }


    /**
     * todo 获取图形验证码  待优化
     *
     * @return
     */
    @Override
    public CaptchaVo getCaptchas() {
        String uuid = IdUtil.simpleUUID();
        String verifyKey = "code:" + uuid;
        CodeGenerator codeGenerator = ReflectUtil.newInstance(UnsignedMathGenerator.class, 1);
        CircleCaptcha captcha = new CircleCaptcha( 200, 100);
        captcha.setGenerator(codeGenerator);
        captcha.createCode();
        // 如果是数学验证码，使用SpEL表达式处理验证码结果
        String code = captcha.getCode();
        if (true) {
            ExpressionParser parser = new SpelExpressionParser();
            Expression exp = parser.parseExpression(code.replaceAll("=",""));
            code = exp.getValue(String.class);
        }
        cacheUtil.set(verifyKey, code, 60);
        CaptchaVo captchaVo = new CaptchaVo();
        captchaVo.setUuid(uuid);
        captchaVo.setImg(captcha.getImageBase64Data());
        return captchaVo;
    }

    /**
     * 忘记密码
     *
     * @param forgetForm
     * @return
     */
    @Override
    public Boolean forget(ForgetForm forgetForm) {
        // 1. 参数校验
        String username = forgetForm.getUsername();
        if (username == null){
            throw new BusinessException(ErrorCode.USERNAME_NOT_FOUND_ERROR);
        }
        // 2. 类型不能为空
        if (forgetForm.getType() == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 3. 比对验证码
        if (forgetForm.getType() == "EMAIL"){
            String code = cacheUtil.get("captcha:forget:" + forgetForm.getEmail());
            if (!forgetForm.getCode().equals(code)){
                throw new BusinessException(ErrorCode.CODE_ERROR);
            }
        }else if (forgetForm.getType() == "PHONE"){
            String code = cacheUtil.get("captcha:forget:" + forgetForm.getPhone());
            if (!forgetForm.getCode().equals(code)){
                throw new BusinessException(ErrorCode.CODE_ERROR);
            }
        }
        // 4. 允许修改密码
        return true;


    }
}
